package cn.demoncat.util.web;

import cn.demoncat.util.exception.ParamRuntimeException;
import cn.demoncat.util.lang.MapUtil;
import cn.demoncat.util.lang.constant.CharsetConstant;
import cn.demoncat.util.lang.constant.StringConstant;
import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 描述：URL处理工具
 *
 * @author yxl
 *
 * @version 2.0
 *
 * @since 2016-12-20
 */
public class UrlUtil {

	/**
	 * 内部请求的PATH前缀
	 */
	public static final String[] REST_PATH_PRE = {
			// REST接口前缀
			"/rest",
			// Spring Boot监控服务的URL前缀(对应 management.context-path 配置)
			"/actuator",
			// 错误页面
			"/error"
	};
	
	
	/**
	 * 功能描述：URL编码
	 *
	 * @param url
	 * @return
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-20
	 */
	public static String encode(String url) {
		if (StringUtils.isBlank(url)) {
			return StringConstant.EMPTY;
		}
		try {
			url = URLEncoder.encode(url, CharsetConstant.UTF8);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return url;
	}

	/**
	 * 功能描述：URL解码
	 *
	 * @param url
	 * @return
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-20
	 */
	public static String decode(String url) {
		if (StringUtils.isBlank(url)) {
			return StringConstant.EMPTY;
		}
		try {
			url = URLDecoder.decode(url, CharsetConstant.UTF8);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return url;
	}

	/**
	 * 功能描述：将URL查询参数规范的字符串转换为Map
	 *
	 * @param urlParams 如 k1=v1&k2=v2，转换时会进行URL解码参数，所以如果参数中可能包含&时应使用URL编码参数
	 * @return
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-20
	 */
	public static Map<String, String> toMap(String urlParams) {
		Map<String, String> map = new LinkedHashMap<>();
		// 参数为空时返回空Map
		if (StringUtils.isBlank(urlParams)) {
			return map;
		}
		// URL解码
		urlParams = UrlUtil.decode(urlParams);
		// 切割
		String[] arr;
		for (String s : urlParams.split(StringConstant.PARAM_SEPARATOR)) {
			arr = s.split(StringConstant.EQUAL);
			if (arr.length == 2) {
				map.put(arr[0], arr[1]);
			} else {
				map.put(arr[0], StringConstant.EMPTY);
			}
		}
		return map;
	}

	/**
	 * 将Map转换为URL查询参数规范的字符串 
	 *
	 * @param  url
	 * @param  params	参数：k=v
	 * @return url?k1=v1&k2=v2
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-20
	 */
	public static String toUrl(String url, Map<String, String> params) {
		// 查询参数
		String param = MapUtil.toUrl(params);
		// 拼接
		if (param.isEmpty()) {
			return url;
		} else {
			if (url.contains(StringConstant.QUESTION)) {
				return url + StringConstant.PARAM_SEPARATOR + param;
			} else {
				return url + StringConstant.QUESTION + param;
			}
		}
	}



	/**
	 * 将Url地址转换为URL对象
	 *
	 * @param  url
	 * @return 
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-20
	 */
	public static URL getUrl(String url) {
		// 非空校验
		if (StringUtils.isBlank(url)) {
			throw ParamRuntimeException.NULL;
		}
		// 去除Hash，创建URL
		try {
			return new URL(trimHash(url));
		} catch (MalformedURLException e) {
			throw new ParamRuntimeException("URL格式错误", e);
		}
	}

	/**
	 * 去除HASH
	 *
	 * @param url
	 * @return
	 *
	 * @author 延晓磊
	 * @since 2021年02月20日
	 */
	public static String trimHash(String url){
		int i = url.indexOf("#");
		if (i > 0) {
			return url.substring(0, i);
		}else{
			return url;
		}
	}

	/**
	 * 获取URL地址的协议部分
	 * <p>
	 * http://localhost:8320/login?id=10 	>	http
	 * http://www.demoncat.cn/login?id=10	>	http
	 *
	 * @param  url
	 * @return
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-20
	 */
	public static String getProtocol(String url) {
		return getUrl(url).getProtocol();
	}

	/**
	 * 获取URL地址的域名(主机名)部分
	 * <p>
	 * http://localhost:8320/login?id=10 	>	localhost
	 * http://www.demoncat.cn/login?id=10	>	www.demoncat.cn
	 *
	 * @param  url
	 * @return
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-20
	 */
	public static String getHost(String url) {
		return getUrl(url).getHost();
	}

	/**
	 * 获取URL地址的Domain(一级域名)
	 * <p>
	 * http://localhost:8320/login?id=10 	>	localhost
	 * http://www.demoncat.cn/login?id=10	>	demoncat.cn
	 *
	 * @param  url
	 * @return
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-20
	 */
	public static String getDomain(String url) {
		url = getHost(url);
		if (url.isEmpty()) {
			return StringConstant.EMPTY;
		}
		String[] arr = StringUtils.split(url, '.');
		int len = arr.length;
		// localhost或一级域名
		if (len == 1 || len == 2) {
			return url;
		} else {
			return arr[len - 2] + StringConstant.POINT + arr[len - 1];
		}
	}

	/**
	 * 获取URL地址的路径部分和参数部分
	 * <p>
	 * http://localhost:8320/login?id=10 	>	/login?id=10
	 * http://www.demoncat.cn/login?id=10	>	/login?id=10
	 *
	 * @param  url
	 * @return URL的路径和参数，如 /query/index.do?name=111&value=222
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-20
	 */
	public static String getPathParam(String url) {
		return getUrl(url).getFile();
	}

	/**
	 * 获取URL地址的Path(路径)部分
	 * <p>
	 * http://localhost:8320/login?id=10 	>	/login
	 * http://www.demoncat.cn/login?id=10	>	/login
	 *
	 * @param  url
	 * @return
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-20
	 */
	public static String getPath(String url) {
		return getUrl(url).getPath();
	}

	/**
	 * 获取URL地址的Param(查询参数)部分
	 * <p>
	 * http://localhost:8320/login?id=10 	>	id=10
	 * http://www.demoncat.cn/login?id=10	>	id=10
	 *
	 * @param  url
	 * @return
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-20
	 */
	public static String getParam(String url) {
		return getUrl(url).getQuery();
	}
	
	/**
	 * 通过URL的PATH，判断是否为内部REST调用的URL
	 * 
	 * @param path
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年9月10日
	 */
	public static boolean isRestUrl(String path) {
		if (StringUtils.isNotBlank(path)) {
			for (String pre : REST_PATH_PRE) {
				if (path.startsWith(pre)) {
					return true;
				}
			}
		}
		return false;
	}
	
	
}
